package com.qdxwx.common.utils;

import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 转换类
 * Qdx NetSchool Platform
 * @author qdxwx
 * @updateTime 2022/5/25
 * @description
 */
public class TKConvert {

    public static void main(String[] args) {
        String dateStr = "qdx123";

        System.out.println(toPWD(dateStr));

    }

    /**
     * 转换为字符串
     * 如果给定的值为null，或者转换失败，返回默认值
     * 转换失败不会报错
     *
     * @param value 被转换的值
     * @param defaultValue 转换错误时的默认值
     * @return 结果
     */
    public static String toStr(Object value, String defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        return value.toString().trim();
    }

    /**
     * 转换为字符串
     * 如果给定的值为 null，或者转换失败，返回默认值 null
     * 转换失败不会报错
     *
     * @param value 被转换的值
     * @return 结果
     */
    public static String toStr(Object value)
    {
        return toStr(value, null);
    }

    /**
     * 用户密码加密
     *
     * @param inputStr
     * @return SHA256
     */
    public static String toPWD(String inputStr) {
        return toEncryptString("TI-KE-PWD-" + inputStr, "SHA-256");
    }

    /*
     * 将指字符串转换为SHA加密字符串
     *
     * @param inputStr 需要转换的字符
     * @return 加密字符串

    //public static String toSHA(String inputStr) {
    //    return toEncryptString(inputStr, "SHA");
    //}
     */
    /*
     * 将指字符串转换为MD5加密字符串
     *
     * @param inputStr 需要转换的字符
     * @return 加密字符串
     */
    public static String toMD5(String inputStr) {
        return toEncryptString(inputStr, "MD5");
    }

    /**
     *
     * @param appId
     * @param appKey
     * @param timeStamp
     * @return
     */
    public static String toToken(String appId, String appKey, String timeStamp) {
        return toEncryptString("TI-KE-TOKEN-" + appId + "-" + appKey + "-" + timeStamp,"SHA");
    }

    public static String toToken(int appId, String appKey, long timeStamp) {
        return toEncryptString("TI-KE-TOKEN-" + appId + "-" + appKey + "-" + timeStamp,"SHA");
    }

    /**
     * 将指字符串转换为指定算法加密字符串
     *
     * @param inputStr  需要转换的字符
     * @param algorithm 指定算法(MD5,SHA...)
     * @return 加密字符串
     */
    public static String toEncryptString(String inputStr, String algorithm) {
        if (inputStr == null) return null;
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            md.update(inputStr.getBytes());
            byte[] bytes = md.digest();
            StringBuilder hexString = new StringBuilder();
            for (byte value : bytes) {
                String shaHex = Integer.toHexString(value & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static  String toURLEncode(String inputStr) {
        return toURLEncode(inputStr, "utf-8");
    }

    /**
     *
     * @param inputStr
     * @param enc
     * @return
     */
    public static  String toURLEncode(String inputStr, String enc) {
        if (inputStr == null || inputStr.trim().length() < 1) return "";
        try {
            return URLEncoder.encode(inputStr, enc);
        } catch (Exception ex) {
            return "";
        }
    }

    /**
     *
     * @param inputStr
     * @return
     */
    public static String toURLDecode(String inputStr) {
        return toURLDecode(inputStr, "utf-8");
    }

    /**
     *
     * @param inputStr
     * @param enc
     * @return
     */
    public static String toURLDecode(String inputStr, String enc) {
        if (inputStr == null || inputStr.trim().length() < 1) return "";
        try {
            return URLDecoder.decode(inputStr, enc);
        } catch (Exception ex) {
            return "";
        }
    }
    /**
     * 将字符串转为数字
     *
     * @param input 字符串
     * @return 如出错，返回0
     */
    public static Integer toInteger(Object input) { return toInteger(input, 0);    }
    /**
     * 将字符串转为数字
     *
     * @param input 字符串
     * @param def   默认值
     * @return 如出错，返回默认值
     */
    public static Integer toInteger(Object input, Integer def) {
        if (input == null) {
            return def;
        }
        if (input instanceof Integer) {
            return (Integer) input;
        }
        if (input instanceof Number) {
            return ((Number) input).intValue();
        }
        try {
            return Integer.parseInt(input.toString());
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 将字符串转为64位数字
     *
     * @param input 字符串
     * @return 如出错，返回0
     */
    public static Long toLong(Object input) {
        return toLong(input, 0L);
    }

    public static Long toLong(String input) {
        return toLong(input, 0L);
    }

    /**
     * 将字符串转为64位数字
     *
     * @param input 字符串
     * @param def   默认值
     * @return 如出错，返回默认值
     */
    public static Long toLong(Object input, Long def) {
        if (input == null) {
            return def;
        }
        if (input instanceof Long) {
            return (Long) input;
        }
        if (input instanceof Number) {
            return ((Number) input).longValue();
        }
        try {
            // 支持科学计数法
            return new BigDecimal(input.toString()).longValue();
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 转换为Integer数组
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static List<Integer> toIntList(String str)
    {
        return toIntList(str, ",");
    }

    /**
     * 转换为Integer数组
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static Integer[] toIntArray(String str)
    {
        return toIntArray(str, ",");
    }

    /**
     * 转换为Long数组
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static Long[] toLongArray(String str)
    {
        return toLongArray(str, ",");
    }


    /**
     * 转换为Integer数组
     * @param str 被转换的值
     * @param split 分隔符
     * @return 结果
     */
    public static List<Integer> toIntList(String str, String split) {
        List<Integer> ints = new ArrayList<>();
        if (str == null) {
            return ints;
        }
        for (String s : str.split(split)) {
            ints.add(toInteger(s, 0));
        }
        return ints;
    }

    /**
     * 转换为Integer数组
     * @param str 被转换的值
     * @param split 分隔符
     * @return 结果
     */
    public static Integer[] toIntArray(String str, String split) {
        if (str == null || str.length() < 1) {
            return new Integer[]{};
        }
        String[] arr = str.trim().split(split);
        Integer[] ints = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++) {
            ints[i] = toInteger(arr[i], 0);
        }
        return ints;
    }

    public static List<Long> toLongList(String str) {
        return toLongList(str, ",");
    }

    /**
     * 转换为Integer数组
     * @param str 被转换的值
     * @param split 分隔符
     * @return 结果
     */
    public static List<Long> toLongList(String str, String split) {
        List<Long> ints = new ArrayList<>();
        if (str == null || str.length() < 1) {
            return ints;
        }
        for (String s : str.split(split)) {
            ints.add(toLong(s));
        }
        return ints;
    }

    /**
     * 转换为Long数组
     * @param str 被转换的值
     * @param split 分隔符
     * @return 结果
     */
    public static Long[] toLongArray(String str, String split) {
        if (str == null || str.length() < 1) {
            return new Long[]{};
        }
        String[] arr = str.split(split);
        Long[] longs = new Long[arr.length];
        for (int i = 0; i < arr.length; i++) {
            longs[i] = toLong(arr[i], null);
        }
        return longs;
    }

    /**
     * 转换为String数组
     *
     * @param str 被转换的值
     * @return 结果
     */
    public static String[] toStrArray(String str)
    {
        return toStrArray( str, ",");
    }

    /**
     * 转换为String数组
     * @param str 被转换的值
     * @param split 分隔符
     * @return 结果
     */
    public static String[] toStrArray(String str, String split)
    {
        return str.split(split);
    }


    /**
     * 将字符串转为单精度值
     *
     * @param input 字符串
     * @return 如出错，返回0
     */
    public static Float toFloat(Object input) {
        return toFloat(input, 0F);
    }

    /**
     * 将字符串转为单精度值
     *
     * @param input 字符串
     * @param def   默认值
     * @return 如出错，返回默认值
     */
    public static Float toFloat(Object input, Float def) {
        if (input == null) {
            return def;
        }
        if (input instanceof Float) {
            return (Float) input;
        }
        if (input instanceof Number) {
            return ((Number) input).floatValue();
        }
        try {
            return Float.parseFloat(input.toString().trim());
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 将字符串转为双精度值
     *
     * @param input 字符串
     * @return 如出错，返回0
     */
    public static Double toDouble(Object input) {
        return toDouble(input, 0D);
    }

    /**
     * 将字符串转为双精度值
     *
     * @param input 字符串
     * @param def   默认值
     * @return 如出错，返回默认值
     */
    public static Double toDouble(Object input, Double def) {
        if (input == null) {
            return def;
        }
        if (input instanceof Double) {
            return (Double) input;
        }
        if (input instanceof Number) {
            return ((Number) input).doubleValue();
        }
        try {
            return Double.parseDouble(input.toString().trim());
        } catch (Exception e) {
            return def;
        }
    }
    /**
     * 转换为BigDecimal
     * 如果给定的值为空，或者转换失败，返回默认值
     * 转换失败不会报错
     *
     * @param value 被转换的值
     * @param defaultValue 转换错误时的默认值
     * @return 结果
     */
    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Long) {
            return BigDecimal.valueOf((Long) value);
        }
        if (value instanceof Double) {
            return BigDecimal.valueOf((Double) value);
        }
        if (value instanceof Integer) {
            return new BigDecimal((Integer) value);
        }
        try {
            return new BigDecimal(value.toString());
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 转换为BigDecimal
     * 如果给定的值为空，或者转换失败，返回默认值
     * 转换失败不会报错
     *
     * @param value 被转换的值
     * @return 结果
     */
    public static BigDecimal toBigDecimal(Object value)
    {
        return toBigDecimal(value, BigDecimal.ZERO);
    }
    /**
     * 将字符串转换为数字
     *
     * @param str 要转换字符串
     * @return long
     */
    public static boolean toBoolean(String str) {
        return toBoolean(str, false);
    }
    /**
     * 将字符串转换为数字Long
     *
     * @param str 要转换字符串
     * @param def 转换失败默认值
     * @return long
     */
    public static boolean toBoolean(String str, boolean def) {
        if (str == null || str.equals("")) return def;
        if (str.equals("1") || str.equals("true")) return true;
        if (str.equals("0") || str.equals("false")) return false;
        try {
            return Boolean.parseBoolean(str.toLowerCase());
        } catch (Exception ex) {
            return def;
        }
    }
    /**
     * Date转LocalDate
     *
     * @param date
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static LocalDateTime toLocalDateTime(String strDate) {
        return toLocalDateTime(strDate, LocalDateTime.now());
    }

    public static LocalDateTime toLocalDateTime(String strDate, LocalDateTime def) {
        if (strDate == null) return def;
        try {
            strDate = strDate.replace("/", "")
                    .replace("T", "")
                    .replace("-", "")
                    .replace(":", "")
                    .replace(" ", "")
                    .replace("年", "")
                    .replace("月", "")
                    .replace("日", "");
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
            return LocalDateTime.parse(strDate, df);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * Date转LocalDate
     *
     * @param date
     */
    public static LocalDate toLocalDate(Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDate toLocalDate(String strDate) {
        return toLocalDate(strDate, LocalDate.now());
    }

    public static LocalDate toLocalDate(String strDate, LocalDate def) {
        if (strDate == null) return def;
        try {
            if (strDate.length() > 12) {
                return toLocalDateTime(strDate, def.atStartOfDay()).toLocalDate();
            }
            strDate = strDate.replace("/", "")
                    .replace("T", "")
                    .replace("-", "")
                    .replace(" ", "")
                    .replace("年", "")
                    .replace("月", "")
                    .replace("日", "");
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
            return LocalDate.parse(strDate, df);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * 将对象转为字符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj 对象
     * @return 字符串
     */
    public static String utf8Str(Object obj)
    {
        return str(obj, StandardCharsets.UTF_8);
    }

    /**
     * 将对象转为字符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj 对象
     * @param charsetName 字符集
     * @return 字符串
     */
    public static String str(Object obj, String charsetName)
    {
        return str(obj, Charset.forName(charsetName));
    }

    /**
     * 将对象转为字符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj 对象
     * @param charset 字符集
     * @return 字符串
     */
    public static String str(Object obj, Charset charset) {
        if (null == obj) {
            return null;
        }
        if (obj instanceof String) {
            return (String) obj;
        } else if (obj instanceof byte[] || obj instanceof Byte[]) {
            return str((Byte[]) obj, charset);
        } else if (obj instanceof ByteBuffer) {
            return str((ByteBuffer) obj, charset);
        }
        return obj.toString();
    }

    /**
     * 将byte数组转为字符串
     *
     * @param bytes byte数组
     * @param charset 字符集
     * @return 字符串
     */
    public static String str(byte[] bytes, String charset) {
        return str(bytes, charset == null ? Charset.defaultCharset() : Charset.forName(charset));
    }

    /**
     * 解码字节码
     *
     * @param data 字符串
     * @param charset 字符集，如果此字段为空，则解码的结果取决于平台
     * @return 解码后的字符串
     */
    public static String str(byte[] data, Charset charset) {
        if (data == null) {
            return null;
        }

        if (null == charset) {
            return new String(data);
        }
        return new String(data, charset);
    }

    /**
     * 将编码的byteBuffer数据转换为字符串
     *
     * @param data 数据
     * @param charset 字符集，如果为空使用当前系统字符集
     * @return 字符串
     */
    public static String str(ByteBuffer data, String charset) {
        if (data == null) {
            return null;
        }

        return str(data, Charset.forName(charset));
    }

    /**
     * 将编码的byteBuffer数据转换为字符串
     *
     * @param data 数据
     * @param charset 字符集，如果为空使用当前系统字符集
     * @return 字符串
     */
    public static String str(ByteBuffer data, Charset charset) {
        if (null == charset) {
            charset = Charset.defaultCharset();
        }
        return charset.decode(data).toString();
    }
    /**
     * 半角转全角
     *
     * @param input String.
     * @return 全角字符串.
     */
    public static String toSBC(String input)
    {
        return toSBC(input, null);
    }

    /**
     * 半角转全角
     *
     * @param input String
     * @param notConvertSet 不替换的字符集合
     * @return 全角字符串.
     */
    public static String toSBC(String input, Set<Character> notConvertSet) {
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (null != notConvertSet && notConvertSet.contains(c[i])) {
                // 跳过不替换的字符
                continue;
            }

            if (c[i] == ' ') {
                c[i] = '\u3000';
            } else if (c[i] < '\177') {
                c[i] = (char) (c[i] + 65248);
            }
        }
        return new String(c);
    }

    /**
     * 全角转半角
     *
     * @param input String.
     * @return 半角字符串
     */
    public static String toDBC(String input)
    {
        return toDBC(input, null);
    }

    /**
     * 替换全角为半角
     *
     * @param text 文本
     * @param notConvertSet 不替换的字符集合
     * @return 替换后的字符
     */
    public static String toDBC(String text, Set<Character> notConvertSet) {
        char[] c = text.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (null != notConvertSet && notConvertSet.contains(c[i])) {
                // 跳过不替换的字符
                continue;
            }

            if (c[i] == '\u3000') {
                c[i] = ' ';
            } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
                c[i] = (char) (c[i] - 65248);
            }
        }

        return new String(c);
    }

    /**
     * 数字金额大写转换 先写个完整的然后将如零拾替换成零
     *
     * @param n 数字
     * @return 中文大写数字
     */
    public static String digitUppercase(double n) {
        String[] fraction = {"角", "分"};
        String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};

        String head = n < 0 ? "负" : "";
        n = Math.abs(n);

        StringBuilder s = new StringBuilder();
        for (int i = 0; i < fraction.length; i++) {
            s.append((digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""));
        }
        if (s.length() < 1) {
            s = new StringBuilder("整");
        }
        int integerPart = (int) Math.floor(n);

        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            StringBuilder p = new StringBuilder();
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p.insert(0, digit[integerPart % 10] + unit[1][j]);
                integerPart = integerPart / 10;
            }
            s.insert(0, p.toString().replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i]);
        }
        return head + s.toString().replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }
}
